import CryptoJS from 'crypto-js'
import { getOssAuth } from '@/api/upload'

/**
 * 阿里云OSS上传工具类
 */
class OssUploader {
  constructor() {
    this.ossConfig = null
    this.timeout = 87600 // 24小时
  }

  /**
   * 初始化OSS配置信息
   */
  async initOssConfig() {
    try {
      const response = await getOssAuth()
      if (response.code === 200) {
        this.ossConfig = {
          AccessKeyId: response.result.Credentials.AccessKeyId,
          AccessKeySecret: response.result.Credentials.AccessKeySecret,
          SecurityToken: response.result.Credentials.SecurityToken,
          Region: response.result.Region || 'oss-cn-beijing',
          Bucket: response.result.Bucket || 'cloud-meow',
          Endpoint: response.result.Endpoint || 'https://cloud-meow.oss-cn-beijing.aliyuncs.com'
        }
        return this.ossConfig
      } else {
        throw new Error(response.message || '获取OSS配置失败')
      }
    } catch (error) {
      console.error('初始化OSS配置失败:', error)
      throw error
    }
  }

  /**
   * 生成上传策略
   */
  getPolicyBase64() {
    const date = new Date()
    date.setHours(date.getHours() + this.timeout)
    const expiration = date.toISOString()

    const policyText = {
      expiration: expiration,
      conditions: [
        ['content-length-range', 0, 100 * 1024 * 1024] // 100MB限制
      ]
    }

    return btoa(JSON.stringify(policyText))
  }

  /**
   * 生成签名
   */
  getSignature(policyBase64) {
    if (!this.ossConfig) {
      throw new Error('OSS配置未初始化')
    }

    const signature = CryptoJS.HmacSHA1(policyBase64, this.ossConfig.AccessKeySecret)
    return CryptoJS.enc.Base64.stringify(signature)
  }

  /**
   * 生成文件路径
   */
  generateFileKey(file) {
    const date = new Date()
    const year = date.getFullYear()
    const month = String(date.getMonth() + 1).padStart(2, '0')
    const day = String(date.getDate()).padStart(2, '0')
    
    // 获取文件扩展名
    const fileName = file.name || 'file'
    const suffix = fileName.substring(fileName.lastIndexOf('.'))
    
    // 生成唯一ID
    const uniqueId = Date.now() + Math.random().toString(36).substr(2, 9)
    
    return `${year}/${month}/${day}/${uniqueId}${suffix}`
  }

  /**
   * 上传文件到OSS
   */
  async uploadFile(file, onProgress) {
    try {
      // 确保OSS配置已初始化
      if (!this.ossConfig) {
        await this.initOssConfig()
      }

      const policyBase64 = this.getPolicyBase64()
      const signature = this.getSignature(policyBase64)
      const fileKey = this.generateFileKey(file)

      // 构建FormData
      const formData = new FormData()
      formData.append('key', fileKey)
      formData.append('policy', policyBase64)
      formData.append('OSSAccessKeyId', this.ossConfig.AccessKeyId)
      formData.append('signature', signature)
      formData.append('x-oss-security-token', this.ossConfig.SecurityToken)
      formData.append('success_action_status', '200')
      formData.append('file', file)

      // 上传到OSS
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest()

        // 监听上传进度
        if (onProgress) {
          xhr.upload.addEventListener('progress', (event) => {
            if (event.lengthComputable) {
              const percent = Math.round((event.loaded * 100) / event.total)
              onProgress({ percent })
            }
          })
        }

        xhr.addEventListener('load', () => {
          if (xhr.status === 200) {
            resolve({
              url: fileKey,
              fullUrl: `${this.ossConfig.Endpoint}/${fileKey}`,
              name: file.name
            })
          } else {
            reject(new Error(`上传失败: ${xhr.status}`))
          }
        })

        xhr.addEventListener('error', () => {
          reject(new Error('网络错误'))
        })

        xhr.open('POST', this.ossConfig.Endpoint)
        xhr.send(formData)
      })
    } catch (error) {
      console.error('OSS上传失败:', error)
      throw error
    }
  }

  /**
   * 批量上传文件
   */
  async uploadFiles(files, onProgress) {
    const results = []
    const total = files.length

    for (let i = 0; i < files.length; i++) {
      const file = files[i]
      try {
        const result = await this.uploadFile(file, (progress) => {
          if (onProgress) {
            const overallProgress = {
              current: i + 1,
              total: total,
              percent: Math.round(((i + progress.percent / 100) / total) * 100),
              currentFile: file.name,
              currentPercent: progress.percent
            }
            onProgress(overallProgress)
          }
        })
        results.push(result)
      } catch (error) {
        console.error(`文件 ${file.name} 上传失败:`, error)
        results.push({ error: error.message, name: file.name })
      }
    }

    return results
  }
}

// 创建单例实例
const ossUploader = new OssUploader()

export default ossUploader

// 导出便捷方法
export const uploadToOss = (file, onProgress) => {
  return ossUploader.uploadFile(file, onProgress)
}

export const uploadMultipleToOss = (files, onProgress) => {
  return ossUploader.uploadFiles(files, onProgress)
}